package com.yfp.client.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yfp.client.domain.*;
import com.yfp.client.domain.dto.*;
import com.yfp.client.domain.vo.*;
import com.yfp.client.domain.*;
import com.yfp.client.domain.dto.*;
import com.yfp.client.domain.vo.*;
import com.yfp.client.enums.CouponPackShopStatusEnum;
import com.yfp.client.enums.GoodsTypeEnum;
import com.yfp.client.mapper.*;
import com.yfp.client.service.*;
import com.yfp.client.mapper.*;
import com.yfp.client.service.*;
import com.yfp.client.util.ResponseEnum;
import com.yfp.client.util.SecurityUtils;
import com.yfp.common.core.constant.MqttConstants;
import com.yfp.common.core.enums.OrderTypeEnum;
import com.yfp.common.core.exception.InnerAuthException;
import com.yfp.common.core.utils.StringUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Description:
 * 
 * @CreateDate: 2024/5/24 9:49
 * @UpdateUser: 
 * @UpdateDate: 2024/5/24 9:49
 * @UpdateRemark: 暂无修改
 * @Version: 1.0
 */
@Slf4j
@Service
public class MachineServiceImpl implements MachineService {

    @Autowired
    private MachineMapper machineMapper;
    @Resource
    private DeviceCurrentComboStockMapper deviceCurrentComboStockMapper;
    @Resource
    private ComboMapper comboMapper;
    @Resource
    private ImgResourceMapper imgResourceMapper;
    @Resource
    private TagComboMapper tagComboMapper;
    @Resource
    private TagComboService tagComboService;
    @Resource
    private ComboDetailImgMapper comboDetailImgMapper;
    @Resource
    private PositionTypeMapper positionTypeMapper;
    @Resource
    private MqttGateway mqttGateway;
    @Resource
    private OrderDetailWaitMapper orderDetailWaitMapper;
    @Resource
    private ClientCouponService clientCouponService;
    @Resource
    private MarCouponPackShopService marCouponPackShopService;
    @Resource
    private MarCouponPackService marCouponPackService;
    @Resource
    private OrderService orderService;
    @Resource
    private ClientMapper clientMapper;

    /**
     * 查询客户收藏设备
     *
     * @param clientId    客户ID
     * @param latitude    纬度
     * @param longitude   经度
     * @param machineName 设备名称
     * @param machineId   设备ID
     * @return
     */
    @Override
    public List<MachineVo> findMachines(String clientId, String latitude, String longitude, String machineName, String machineId) {
        return machineMapper.findMachines(clientId, latitude, longitude, machineName, machineId);
    }

    @Override
    public Machine findByMachineId(String machineId) {
        return machineMapper.findByMachineId(machineId);
    }


    @Override
    public List<DeviceInfoVO> getByIds(List<String> machineIds) {
        if (machineIds.isEmpty()) {
            return new ArrayList<>();
        }
        return machineMapper.getByIds(machineIds);
    }

    @Override
    @Transactional
    public MachineComboVO machineComboList(String machineId) {

        MachineComboVO machineComboVO = new MachineComboVO();

        if (StringUtils.isEmpty(machineId)) {
            return machineComboVO;
        }

        String clientId = null;
        try {
            clientId = SecurityUtils.getClientId();
        } catch (InnerAuthException e) {
            log.info("computeEstimatedPrice,用户未登录时调用");
        }


        // 如果用户为新用户，切换点位标签为当前设备的点位
        List<String> orderIdList = orderService.orderIdList(clientId);
        if (CollUtil.isEmpty(orderIdList)) {
            Machine machine = machineMapper.getById(machineId);
            clientMapper.updatePositionId(clientId, machine.getPositionId());
        }


        List<ComboListVO> comboStockList = deviceCurrentComboStockMapper.selectAll(machineId);
        // 获取等待数量
        Integer awaitNum = orderService.getAwaitNum(machineId);
        machineComboVO.setAwaitNum(awaitNum);
        // 转换成map
        Map<String, ComboListVO> stockMap = comboStockList.stream().collect(Collectors.toMap(ComboListVO::getComboId, Function.identity()));
        // 抽出套餐id集合
        List<String> comboIdList = comboStockList.stream().map(ComboListVO::getComboId).collect(Collectors.toList());
        // 如果套餐id为空
        if (comboIdList.isEmpty()) {
            return machineComboVO;
        }
        ArrayList<ComboListVO> comboListVOs = new ArrayList<>();
        // 根据套餐id获取套餐详细信息
        List<AppletComboInfoDto> appletComboInfoDtos = comboDetailData(comboIdList);
        // 详细信息转成map
        Map<String, AppletComboInfoDto> appletComboInfoDtoMap = appletComboInfoDtos.stream().collect(Collectors.toMap(AppletComboInfoDto::getComboId, Function.identity()));
        for (String comboId : stockMap.keySet()) {
            ComboListVO comboListVO = stockMap.get(comboId);
            // 如果包含则赋值
            if (appletComboInfoDtoMap.containsKey(comboId)) {
                AppletComboInfoDto appletComboInfoDto = appletComboInfoDtoMap.get(comboId);
                comboListVO.setAppletComboInfoDto(appletComboInfoDto);
            }
            comboListVOs.add(comboListVO);
        }



        if (StrUtil.isNotBlank(clientId)) {
            // 计算预估到手价格
            // 列表中的套餐需要分别判断，分别取优惠力度最大优惠券的预估金额
            List<ComboListVO> comboListVOS = clientCouponService.computeEstimatedPrice(machineId, comboListVOs);
            machineComboVO.setList(comboListVOS);
        } else {
            machineComboVO.setList(comboListVOs);
        }
        return machineComboVO;
    }

    /**
     * 获取套餐详细信息
     */
    @Override
    public List<AppletComboInfoDto> comboDetailData(List<String> comboIdList) {

        List<AppletComboInfoDto> list = new ArrayList<>();

        // 根据套餐id查询套餐
        LambdaQueryWrapper<Combo> comboWrapper = new LambdaQueryWrapper<Combo>().in(Combo::getComboId, comboIdList);
        List<Combo> comboList = comboMapper.selectList(comboWrapper);
        Map<String, Combo> comboMap = comboList.stream().collect(Collectors.toMap(Combo::getComboId, Function.identity()));


        // 获取套餐图片
        List<String> thumbList = comboList.stream().map(Combo::getThumb).collect(Collectors.toList());
        LambdaQueryWrapper<ImgResource> ImgWrapper = new LambdaQueryWrapper<ImgResource>().in(ImgResource::getImgId, thumbList);
        List<ImgResource> imgResourceList = imgResourceMapper.selectList(ImgWrapper);
        Map<String, String> urlMap = imgResourceList.stream().collect(Collectors.toMap(ImgResource::getImgId, ImgResource::getUrl));

        // 标签
        LambdaQueryWrapper<TagCombo> tagComboLambdaQueryWrapper = new LambdaQueryWrapper<>();
        List<TagCombo> tagCombos = tagComboMapper.selectList(tagComboLambdaQueryWrapper);

        LambdaQueryWrapper<ComboDetailImg> comboDetailImgLambdaQueryWrapper = new LambdaQueryWrapper<ComboDetailImg>().in(ComboDetailImg::getComboId, comboIdList).eq(ComboDetailImg::getImgType, 2);
        List<ComboDetailImg> comboDetailImgList = comboDetailImgMapper.selectList(comboDetailImgLambdaQueryWrapper);

        // 图片资源
        List<ComboDetailData> imgResources = comboMapper.imgResource(comboIdList);
        // 视频资源
        List<ComboDetailData> videoResources = comboMapper.videoResource(comboIdList);

        for (String comboId : comboIdList) {
            AppletComboInfoDto appletComboInfoDto = new AppletComboInfoDto();

            // 套餐id
            appletComboInfoDto.setComboId(comboId);
            // 套餐名称
            Combo combo = comboMap.get(comboId);
            appletComboInfoDto.setComboName(combo.getName());
            // 保质期
            appletComboInfoDto.setExpireDay(combo.getExpireDay());
            // 加热时长
            appletComboInfoDto.setHeatTime(combo.getHeatTime());
            // 图片
            String thumb = combo.getThumb();
            appletComboInfoDto.setThumbUrl(urlMap.get(thumb));
            appletComboInfoDto.setComboInfoImg(combo.getComboInfoImg());
            // 标签
            String tagId = combo.getTagId();
            if (!StringUtils.isEmpty(tagId)) {
                List<String> tagIds = Arrays.asList(tagId.split(","));
                List<TagCombo> tagComboList = tagCombos.stream().filter(tagCombo -> tagIds.contains(tagCombo.getTagId())).collect(Collectors.toList());
                appletComboInfoDto.setTagComboList(tagComboList);
            }

            // 营销
            MarketingDTO marketing = new MarketingDTO();
            marketing.setApplietAmount(combo.getSalePrice());
            marketing.setVipAmount(combo.getVipPrice());
            marketing.setDeviceAmount(combo.getSalePrice());
            appletComboInfoDto.setMarketing(marketing);

            List<ComboDetailData> dataArrayList = new ArrayList<>();
            // 图片资源
            List<ComboDetailData> dataList = imgResources.stream().filter(comboDetailData -> comboDetailData.getComboId().equals(comboId)).collect(Collectors.toList());
            dataArrayList.addAll(dataList);
            // 视频资源
            List<ComboDetailData> collect = videoResources.stream().filter(comboDetailData -> comboDetailData.getComboId().equals(comboId)).collect(Collectors.toList());
            dataArrayList.addAll(collect);
            appletComboInfoDto.setComboDetailData(dataArrayList);

            // 辣度
            Tastes tastes = new Tastes();
            tastes.setSpicy(combo.getTaste());
            appletComboInfoDto.setTastes(tastes);
            list.add(appletComboInfoDto);
        }
        return list;
    }

    /**
     * 是否营业
     *
     * @param machineId 机器id
     * @return {@link Boolean}
     */
    @Override
    public Boolean isBusinessOpenByMachineId(String machineId) {
        PositionType positionType = positionTypeMapper.getSaleTimeByMachineId(machineId);
        Assert.isFalse(ObjUtil.hasNull(positionType), "未查询到相关数据");
        Assert.isFalse(ObjUtil.hasNull(positionType.getSaleBeginTime(), positionType.getSaleEndTime()), "未查询到相关数据");
        DateTime begin = DateUtil.parse(positionType.getSaleBeginTime());
        DateTime end = DateUtil.parse(positionType.getSaleEndTime());
        return DateUtil.isIn(new Date(), begin, end);
    }

    /**
     * 通知设备支付状态
     *
     * @param orderCombo   订单套餐
     * @param orderDetails 订单详情
     * @param orderLists   订单列表
     */
    @Override
    public void notifyDevicePayStatus(OrderCombo orderCombo, List<OrderDetail> orderDetails, List<OrderList> orderLists) {
        OrderList firstOrderList = CollUtil.getFirst(orderLists);
        if (StrUtil.equals(OrderTypeEnum.WeChat.getCode().toString(), firstOrderList.getOrderType())) {
            return;
        }
        if (NumberUtil.equals(GoodsTypeEnum.VIRTUAL.getCode(), firstOrderList.getGoodsType())) {
            return;
        }

        OrderNotifyPayStatusDTO orderNotifyPayStatusDTO = new OrderNotifyPayStatusDTO();
        orderNotifyPayStatusDTO.setOrderId(orderCombo.getOrderId());
        orderNotifyPayStatusDTO.setPreOrderId(orderCombo.getOrderId());
        orderNotifyPayStatusDTO.setPayStatus(true);
        orderNotifyPayStatusDTO.setPayTime(firstOrderList.getPayTime().getTime());

        MqttDTO<MakePackageDTO> orderMakeDTOMqttDTO = new MqttDTO<>();
        orderMakeDTOMqttDTO.setCmd(MqttConstants.NOTICE_PAY_STATUS);
        orderMakeDTOMqttDTO.setPayload(orderNotifyPayStatusDTO);

        /**
         * 主题是设备id
         */
        log.info("通知设备支付状态:{}", JSONUtil.toJsonStr(orderMakeDTOMqttDTO));
        mqttGateway.sendToMqtt(orderCombo.getMachineId(), JSONUtil.toJsonStr(orderMakeDTOMqttDTO));
    }

    @Override
    public String findMarAssociationQrCode(String machineId) {
        return machineMapper.findMarAssociationQrCodeByMachineId(machineId);
    }

    @Override
    public List<Machine> findByPositionIdIn(List<String> positionIds) {
        return machineMapper.findByPositionIdIn(positionIds);
    }

    @Override
    public List<MarCouponPackShopVO> couponPackList(String cityName) {
        log.info("城市名称:{}", cityName);
        String clientId = null;
        try {
            clientId = SecurityUtils.getClientId();
            if (StringUtils.isEmpty(cityName)){
                cityName = SecurityUtils.getCityName();
            }
        } catch (Exception e) {

        }
        String finalClientId = clientId;

        // 获取上架的礼包
        List<MarCouponPackShop> marCouponPackShops1 = marCouponPackShopService.listByStatus(CouponPackShopStatusEnum.ON_SHELF.getCode(), cityName);
        // 获取上架中-已售罄的礼包
        List<MarCouponPackShop> marCouponPackShops3 = marCouponPackShopService.listByStatus(CouponPackShopStatusEnum.SOLD_OUT.getCode(), cityName);
        // 组合两个list
        List<MarCouponPackShop> marCouponPackShops = Stream.concat(marCouponPackShops1.stream(), marCouponPackShops3.stream()).collect(Collectors.toList());

        // 获取礼包名称
        List<Long> couponPackIdlist = marCouponPackShops.stream().map(MarCouponPackShop::getCouponPackId).collect(Collectors.toList());
        List<MarCouponPack> marCouponPacks = marCouponPackService.listByIds(couponPackIdlist);
        Map<Long, String> marCouponPackMap = marCouponPacks.stream().collect(Collectors.toMap(MarCouponPack::getId, MarCouponPack::getPackName));

        // 获取礼包对应的优惠券
        Map<Long, List<MarCoupon>> MarCouponMapByCouponPackId = marCouponPackService.listCouponByCouponPackIds(couponPackIdlist);

        // 获取标签名称
        List<String> tagIdlist = marCouponPackShops.stream().map(MarCouponPackShop::getTagId).collect(Collectors.toList());
        List<TagCombo> tagCombos = tagComboService.listByTagIds(tagIdlist);
        Map<String, String> tagComboMap = tagCombos.stream().collect(Collectors.toMap(TagCombo::getTagId, TagCombo::getTagName));
        // 转换数据格式
        List<MarCouponPackShopVO> packShopVOList = marCouponPackShops.stream().sorted(Comparator.comparing(MarCouponPackShop::getSort, Comparator.naturalOrder())).map(marCouponPackShop -> {
            MarCouponPackShopVO packShopVO = BeanUtil.toBean(marCouponPackShop, MarCouponPackShopVO.class);
            String packName = marCouponPackMap.getOrDefault(marCouponPackShop.getCouponPackId(), "");
            String tagName = tagComboMap.getOrDefault(marCouponPackShop.getTagId(), "");
            packShopVO.setName(packName);
            packShopVO.setTagName(tagName);

            // 判断是否可购买
            List<MarCoupon> marCoupons = MarCouponMapByCouponPackId.getOrDefault(marCouponPackShop.getCouponPackId(), new ArrayList<>());
            if (Objects.isNull(finalClientId)) {
                packShopVO.setCanBuy(BooleanUtil.toInteger(Boolean.TRUE));
            } else {
                boolean canBuy = marCoupons.stream().allMatch(item -> {
                    ResponseEnum responseEnum = marCouponPackShopService.verifyCouponBoolean(item.getId(), marCouponPackShop.getCouponPackId(), finalClientId);
                    return ResponseEnum.OPERATOR_SUCCESS.getCode().equals(responseEnum.getCode());
                });
                packShopVO.setCanBuy(BooleanUtil.toInteger(canBuy));
            }
            return packShopVO;
        }).collect(Collectors.toList());
        log.info("礼包packShopVOList：{}", JSONObject.toJSONString(packShopVOList));
        return packShopVOList;
    }

    /**
     * 获取最近设备的点位id
     * @param latitude
     * @param longitude
     * @return
     */
    @Override
    public MachineVo shortDistancePositionId(String latitude, String longitude) {
        return machineMapper.shortDistancePositionId(latitude,longitude);
    }
}
